package org.nox.helloseries.factory;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Factory, gestion des singletons
 */
public final class HelloSeriesServiceFactory
{
    private static final Logger LOG = LoggerFactory.getLogger( HelloSeriesServiceFactory.class );

    // Map de singleton de services
    private static Map<Class<?>, Object> instanciationList = new HashMap<>();

    private static final String PACKAGE_IMPL = "impl";

    private static final String INSTANCIATION_TYPE = "Default";

    private HelloSeriesServiceFactory()
    {
        // Fu
    }

    public static <O extends Object> O createOrGetService( Class<O> clazz )
    {
        LOG.debug( "Recherche du singleton " + clazz.getSimpleName() );
        // Cas où le contexte contient le service
        if ( instanciationList.containsKey( clazz ) )
        {
            LOG.info( "Récupération du singleton de " + clazz.getSimpleName() );
            return (O) instanciationList.get( clazz );
        }

        // Sinon instanciation du service en reflection
        try
        {
            Class<?> classeServiceCible = Class.forName( clazz.getName().replace( clazz.getSimpleName(), PACKAGE_IMPL + "." + INSTANCIATION_TYPE + clazz.getSimpleName() ) );
            // Instanciation de la classe
            Object target = classeServiceCible.newInstance();
            // Enregistrement dans la map d'instance
            LOG.debug( "Création du singleton de " + clazz.getSimpleName() );
            instanciationList.put( clazz, target );
            return (O) target;
        }
        catch ( ClassNotFoundException e )
        {
            LOG.warn( "Impossible d'instancier le service : service non trouvé [" + e.getMessage() + "]" );
        }
        catch ( InstantiationException | IllegalAccessException e )
        {
            LOG.error( "Impossible d'instancier le service", e );
        }

        return null;
    }

    public static void purge()
    {
        instanciationList.clear();
    }

    public static Map<Class<?>, Object> getInstanciationList()
    {
        return instanciationList;
    }

    public static int getInstanciationListSize()
    {
        return instanciationList.size();
    }
}
